﻿using HybridCLR.Editor.Commands;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;
using YooAsset;
using YooAsset.Editor;

namespace HybridCLR.Editor
{
    public static class BuildAssetsCommand
    {

        [MenuItem("Build/BuildAssembliesToDLC")]
        public static void BuildAssembliesToAssetUpdates()
        {
            BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
            CompileDllCommand.CompileDll(target);
            CopyAOTMetaAssembliesToAssetUpdates();
            CopyHotFixAssembliesToAssetUpdates();
            AssetDatabase.Refresh();
        }
        [MenuItem("Build/CopyAOTMetaAssembliesToDLC")]
        public static void CopyAOTMetaAssembliesToAssetUpdates()
        {
            var target = EditorUserBuildSettings.activeBuildTarget;
            string aotAssembliesSrcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
            string aotAssembliesDstDir = "Assets/DLC/HybridCLR/Metas";
            Directory.CreateDirectory(aotAssembliesDstDir);
            foreach (var dll in AOTGenericReferences.PatchedAOTAssemblyList)
            {
                string srcDllPath = $"{aotAssembliesSrcDir}/{dll}";
                if (!File.Exists(srcDllPath))
                {
                    Debug.LogError($"ab中添加AOT补充元数据dll:{srcDllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成，因此需要你先构建一次游戏App后再打包。");
                    continue;
                }
                string dllBytesPath = $"{aotAssembliesDstDir}/{dll.Replace(".dll", ".bytes")}";
                File.Copy(srcDllPath, dllBytesPath, true);
                Debug.Log($"[CopyAOTAssemblies] copy AOT dll {srcDllPath} -> {dllBytesPath}");
            }
            AssetDatabase.Refresh();
        }
        [MenuItem("Build/CopyHotFixAssembliesToDLC")]
        public static void CopyHotFixAssembliesToAssetUpdates()
        {
            var target = EditorUserBuildSettings.activeBuildTarget;

            string hotfixDllSrcDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
            string hotfixAssembliesDstDir = "Assets/DLC/HybridCLR/HotFix";
            Directory.CreateDirectory(hotfixAssembliesDstDir);

            foreach (var dll in SettingsUtil.HotUpdateAssemblyFilesExcludePreserved)
            {
                string dllPath = $"{hotfixDllSrcDir}/{dll}";
                string dllBytesPath = $"{hotfixAssembliesDstDir}/{dll.Replace(".dll", ".bytes")}";
                File.Copy(dllPath, dllBytesPath, true);
                Debug.Log($"[CopyHotUpdateAssemblies] copy hotfix dll {dllPath} -> {dllBytesPath}");
            }
            AssetDatabase.Refresh();
        }

        [MenuItem("Build/BuildYooAssetsbundle(HybridCLR)")]
        public static void BuildYooAssetsbundleHybridCLR()
        {
            BuildAssembliesToAssetUpdates();
            BulidYooAssetsbundle(EditorUserBuildSettings.activeBuildTarget);
            Application.OpenURL($"file:///{AssetBundleBuilderHelper.GetDefaultBuildOutputRoot()}/{EditorUserBuildSettings.activeBuildTarget}");
        }
        [MenuItem("Build/BuildYooAssetsbundle")]
        public static void BuildYooAssetsbundle()
        {
            BulidYooAssetsbundle(EditorUserBuildSettings.activeBuildTarget);
            Application.OpenURL($"file:///{AssetBundleBuilderHelper.GetDefaultBuildOutputRoot()}/{EditorUserBuildSettings.activeBuildTarget}");
        }
        public static void BulidYooAssetsbundle(BuildTarget _buildTarget)
        {
            
            var PackageVersion = $"{DateTime.Now.DayOfYear}.{DateTime.Now.Hour}.{DateTime.Now.Minute}";
            foreach (var Package in AssetBundleCollectorSettingData.Setting.Packages)
            {
                var PackageName = Package.PackageName;
                var BuildPipeline = AssetBundleBuilderSetting.GetPackageBuildPipeline(PackageName);
                var fileNameStyle = AssetBundleBuilderSetting.GetPackageFileNameStyle(PackageName, BuildPipeline);
                var buildinFileCopyOption = AssetBundleBuilderSetting.GetPackageBuildinFileCopyOption(PackageName, BuildPipeline);
                var buildinFileCopyParams = AssetBundleBuilderSetting.GetPackageBuildinFileCopyParams(PackageName, BuildPipeline);
                var compressOption = AssetBundleBuilderSetting.GetPackageCompressOption(PackageName, BuildPipeline);
                
                BuiltinBuildParameters buildParameters = new BuiltinBuildParameters();
                buildParameters.BuildOutputRoot = AssetBundleBuilderHelper.GetDefaultBuildOutputRoot();
                buildParameters.BuildinFileRoot = AssetBundleBuilderHelper.GetStreamingAssetsRoot();
                buildParameters.BuildPipeline = BuildPipeline.ToString();
                buildParameters.BuildTarget = _buildTarget;
                buildParameters.PackageName = PackageName;
                buildParameters.PackageVersion = PackageVersion;
                buildParameters.VerifyBuildingResult = true;
                buildParameters.FileNameStyle = fileNameStyle;
                buildParameters.BuildinFileCopyOption = buildinFileCopyOption;
                buildParameters.BuildinFileCopyParams = buildinFileCopyParams;
                buildParameters.EncryptionServices = CreateEncryptionInstance(PackageName,BuildPipeline);
                buildParameters.CompressOption = compressOption;

                BuiltinBuildPipeline pipeline = new BuiltinBuildPipeline();
                var buildResult = pipeline.Run(buildParameters, true);
                if (buildResult.Success)
                    Debug.Log("YooAssets Build AssetBundle OK!");
                else
                    Debug.LogError("YooAssets Build AssetBundle Failed!");
            }
        }

        /// <summary>
        /// 创建加密类实例
        /// </summary>
        public static IEncryptionServices CreateEncryptionInstance(string PackageName,string BuildPipeline)
        {
            var encyptionClassName = AssetBundleBuilderSetting.GetPackageEncyptionServicesClassName(PackageName, BuildPipeline);
            var encryptionClassTypes = EditorTools.GetAssignableTypes(typeof(IEncryptionServices));
            var classType = encryptionClassTypes.Find(x => x.FullName.Equals(encyptionClassName));
            if (classType != null)
                return (IEncryptionServices)Activator.CreateInstance(classType);
            else
                return null;
        }
    }
}
